/*
 * DetectorConstruction.cc
 *
 *  Created on: 07.05.2011
 *      Author: ed
 */

#include "DetectorConstruction.hh"
#include "G4Material.hh"
#include "G4MaterialPropertiesTable.hh"
#include "G4Box.hh"
#include "G4Tubs.hh"
#include "G4LogicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4OpticalSurface.hh"
#include "G4LogicalBorderSurface.hh"
#include "G4SDManager.hh"
#include "G4GeometryManager.hh"
#include "AbsorptionCounter.hh"
DetectorConstruction::DetectorConstruction()
{
	lAbs = 0;
	lSc = 0;
}
DetectorConstruction::DetectorConstruction(G4int LAbs,G4int LSc)
{
	lAbs = LAbs;
	lSc = LSc;
}
DetectorConstruction::~DetectorConstruction(){}
G4VPhysicalVolume *DetectorConstruction::Construct()
{
	const G4double boxW = 10*cm,boxH = 5*cm,boxD = 10*cm;
	const G4double aerogelBoxW = 5*cm,aerogelBoxH = 3*cm, aerogelBoxD = 5*cm;
	const G4double detectorHoleR = 1*cm;
	const G4double aerogelN = 1.05,airN = 1;
	/**
	 * Materials.
	 */
	G4Element* N = new G4Element("Nitrogen", "N", 7 , 14.01*g/mole);
	G4Element* O = new G4Element("Oxygen"  , "O", 8 , 16.00*g/mole);

	G4Material* air = new G4Material("Air", 1.29*mg/cm3, 2);
	air->AddElement(N, 70.*perCent);
	air->AddElement(O, 30.*perCent);


	G4Material* aerogel = new G4Material("Aerogel", 0.1*g/cm3,0);

	G4MaterialPropertiesTable* airMPT = new G4MaterialPropertiesTable();
	G4MaterialPropertiesTable* aerogelMPT = new G4MaterialPropertiesTable();

	G4double energies[1] = {1*eV};
	G4double airRefractiveIndex[1] = {airN};

	G4double aerogelScaterringIndex[1] = {lSc};
	G4double aerogelAbsorptionIndex[1] = {lAbs};
	G4double aerogelRefractiveIndex[1] = {aerogelN};

	aerogelMPT->AddProperty("RAYLEIGH",energies,aerogelScaterringIndex,1);
	aerogelMPT->AddProperty("ABSLENGTH",energies,aerogelAbsorptionIndex,1);
	aerogelMPT->AddProperty("RINDEX",energies,aerogelRefractiveIndex,1);

	airMPT->AddProperty("RINDEX",energies,airRefractiveIndex,1);

	air->SetMaterialPropertiesTable(airMPT);
	aerogel->SetMaterialPropertiesTable(aerogelMPT);
	/**
	 *Volumes.
	 */
	G4Box* worldBox = new G4Box("World Box",boxW*1.5,boxH*1.5,boxD*1.5);
	G4Box* airBox = new G4Box("Air Box",boxW,boxH,boxD);
	G4Box* aerogelBox = new G4Box("Aerogel Box",aerogelBoxW,aerogelBoxH,aerogelBoxD);
	G4Tubs* detectorHole = new G4Tubs("Detector Hole",0,detectorHoleR,1*cm,0,2*pi);

	G4LogicalVolume* detectorHoleLog = new G4LogicalVolume(detectorHole,air,"Detector Hole Logical");
	G4LogicalVolume* worldBoxLog = new G4LogicalVolume(worldBox,air,"Air Box Logical");
	G4LogicalVolume* airBoxLog = new G4LogicalVolume(airBox,air,"Air Box Logical");
	G4LogicalVolume* aerogelBoxLog = new G4LogicalVolume(aerogelBox,aerogel,"Aerogel Box Logical");

	G4VPhysicalVolume* worldBoxPhys = new G4PVPlacement(0,0,worldBoxLog,"World Air Box",0,false,0);
	G4VPhysicalVolume* airBoxPhys = new G4PVPlacement(0,0,airBoxLog,"Air Box",worldBoxLog,false,0);
	aerogelBoxPhys = new G4PVPlacement(0,G4ThreeVector(-1.5*cm,-1*cm,-1.5*cm),aerogelBoxLog,"Aerogel Box",airBoxLog,false,0);

	G4VPhysicalVolume* detectorHolePhys = new G4PVPlacement(new G4RotationMatrix(G4ThreeVector(0,1,0),pi/2),
			G4ThreeVector(boxW+1*cm,0,0),detectorHoleLog,"Detector Hole",worldBoxLog,false,0);
	/**
	 * Surfaces.
	 */
	G4OpticalSurface* boxReflector = new G4OpticalSurface("Reflector");
	boxReflector->SetModel(unified);
	boxReflector->SetFinish(groundbackpainted);
	boxReflector->SetType(dielectric_dielectric);
	const G4int NUM = 2;

	G4double pp[NUM] = {1*eV, 4.144*eV};
	G4double specularlobe[NUM] = {0.0, 0.0};
	G4double specularspike[NUM] = {0.0, 0.0};
	G4double backscatter[NUM] = {0.0, 0.0};
	G4double rindex[NUM] = {0.0, 0.0};
	G4double reflectivity[NUM] = {0.99, 0.99};
	G4double efficiency[NUM] = {0.0, 0.0};

	G4MaterialPropertiesTable* SMPT = new G4MaterialPropertiesTable();

	SMPT -> AddProperty("RINDEX",pp,rindex,NUM);
	SMPT -> AddProperty("SPECULARLOBECONSTANT",pp,specularlobe,NUM);
	SMPT -> AddProperty("SPECULARSPIKECONSTANT",pp,specularspike,NUM);
	SMPT -> AddProperty("BACKSCATTERCONSTANT",pp,backscatter,NUM);
	SMPT -> AddProperty("REFLECTIVITY",pp,reflectivity,NUM);
	SMPT -> AddProperty("EFFICIENCY",pp,efficiency,NUM);
	boxReflector->SetMaterialPropertiesTable(SMPT);
	//G4LogicalSkinSurface* ReflectorLog =
	new G4LogicalBorderSurface("Reflector Surface Log",airBoxPhys,worldBoxPhys,boxReflector);


	G4OpticalSurface* detectorHoleSurface = new G4OpticalSurface("DetectorHole");
	detectorHoleSurface->SetModel(unified);
	detectorHoleSurface->SetFinish(polished);


	G4double pp1[NUM] = {1*eV, 4.144*eV};
	G4double specularlobe1[NUM] = {1, 0.0};
	G4double specularspike1[NUM] = {0.0, 0.0};
	G4double backscatter1[NUM] = {0.0, 0.0};
	G4double rindex1[NUM] = {0.0, 0.0};
	G4double reflectivity1[NUM] = {0.0, 0.0};
	G4double efficiency1[NUM] = {1.0, 1.0};

	G4MaterialPropertiesTable* SMPT1 = new G4MaterialPropertiesTable();

	SMPT1 -> AddProperty("RINDEX",pp1,rindex1,NUM);
	SMPT1 -> AddProperty("SPECULARLOBECONSTANT",pp,specularlobe1,NUM);
	SMPT1 -> AddProperty("SPECULARSPIKECONSTANT",pp,specularspike1,NUM);
	SMPT1 -> AddProperty("BACKSCATTERCONSTANT",pp,backscatter1,NUM);
	SMPT1 -> AddProperty("REFLECTIVITY",pp,reflectivity1,NUM);
	SMPT1 -> AddProperty("EFFICIENCY",pp,efficiency1,NUM);
	detectorHoleSurface->SetMaterialPropertiesTable(SMPT1);

	new G4LogicalBorderSurface("Detector Hole Surface",airBoxPhys,detectorHolePhys,detectorHoleSurface);


	G4SDManager *sdMan = G4SDManager::GetSDMpointer();
	if(sdMan)
	{
		trackerSD = new TrackerSD("Tracker");
		sdMan->AddNewDetector(trackerSD);
		detectorHoleLog->SetSensitiveDetector(trackerSD);
		AbsorptionCounter* counter = new AbsorptionCounter("Counter");
		sdMan->AddNewDetector(counter);
		airBoxLog->SetSensitiveDetector(counter);
		aerogelBoxLog->SetSensitiveDetector(counter);
	}

	return worldBoxPhys;
}
void DetectorConstruction::SetLSc(G4double LSc)
{
	if(LSc==lSc)
		return;
	G4GeometryManager *geometryManager = G4GeometryManager::GetInstance();
	if(geometryManager==0)
	{
		G4cout<<"Geometry manager is not instantiated yet"<<G4endl;
		return;
	}
	geometryManager->OpenGeometry(aerogelBoxPhys);
	G4MaterialPropertiesTable *t = aerogelBoxPhys->GetLogicalVolume()->GetMaterial()->GetMaterialPropertiesTable();
	G4double pe = 1*eV;//PrimariesGenerator::GetPhotonEnergy();
	t->RemoveEntry("RAYLEIGH",pe);
	lSc= LSc;
	t->AddEntry("RAYLEIGH",pe,lSc);
	geometryManager->CloseGeometry(aerogelBoxPhys);
}
void DetectorConstruction::SetLAbs(G4double LAbs)
{
	if(LAbs==lAbs)
		return;
	G4GeometryManager *geometryManager = G4GeometryManager::GetInstance();
	if(geometryManager==0)
	{
		G4cout<<"Geometry manager is not instantiated yet"<<G4endl;
		return;
	}
	geometryManager->OpenGeometry(aerogelBoxPhys);
	G4MaterialPropertiesTable *t = aerogelBoxPhys->GetLogicalVolume()->GetMaterial()->GetMaterialPropertiesTable();
	G4double pe = 1*eV;//PrimariesGenerator::GetPhotonEnergy();
	t->RemoveEntry("ABSLENGTH",pe);
	lAbs = LAbs;
	t->AddEntry("ABSLENGTH",pe,lAbs);
	geometryManager->CloseGeometry(aerogelBoxPhys);
}
G4int DetectorConstruction::GetLightOutput()
{
	return trackerSD->GetLightOutput();
}
G4int DetectorConstruction::GetParticlesPerEvent()
{
	return trackerSD->GetParticlesPerEvent();
}
G4double DetectorConstruction::GetLightCollection()
{
	return trackerSD->GetLightCollection();
}
